home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Developer Toolbox 6.1
/
SGI Developer Toolbox 6.1 - Disc 4.iso
/
src
/
demos
/
VGX
/
shadows
/
pdat.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-08-01
|
9KB
|
270 lines
/*
* Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
* All Rights Reserved.
*
* This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
* the contents of this file may not be disclosed to third parties, copied or
* duplicated in any form, in whole or in part, without the prior written
* permission of Silicon Graphics, Inc.
*
* RESTRICTED RIGHTS LEGEND:
* Use, duplication or disclosure by the Government is subject to restrictions
* as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
* and Computer Software clause at DFARS 252.227-7013, and/or in similar or
* successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
* rights reserved under the Copyright Laws of the United States.
*/
/*
pdat.c - Support for file read/write of glo_object/PolyData structure.
Tim Heidmann, Silicon Graphics
June 26, 1991
*/
#include <stdio.h>
#include "glo_obj.h"
#include "shadows.h"
#include "vect.h"
#define MAXEDGES 10000
#define MAXFACES 10000
Boolean
ReadPDataObj(char *filename, glo_ObjPtr *drawlistp, PolyDataPtr *datalistp) {
/* Try to read a binary drawlist & datalist object file.
Return TRUE on success. */
FILE *inf;
glo_ObjPtr drawlist;
PolyDataPtr datalist;
int nList, nTrip, nListBytes, nTripBytes, version;
int nEdgesBytes, nFacesBytes;
char buf[20];
/* Open the file for reading and check the file type. */
if ((inf = fopen(filename, "r")) == NULL ||
fread(buf, 1, 8, inf) < 8 ||
strncmp(buf, "pdataobj", 8) != 0) return FALSE;
if (fread(&version, 1, sizeof(int), inf) < sizeof(int)) return FALSE;
/* Allocate and read drawlist and triplets */
drawlist = (glo_ObjPtr) malloc(sizeof(glo_ObjTyp));
if (fread(&nList, 1, sizeof(int), inf) < sizeof(int)) return FALSE;
nListBytes = nList * sizeof(int);
drawlist->list = (int *) malloc(nListBytes);
if (fread(&nTrip, 1, sizeof(int), inf) < sizeof(int)) return FALSE;
nTripBytes = nTrip * 3 * sizeof(float);
drawlist->t = (float **) malloc(nTripBytes);
if (fread(drawlist->list, 1, nListBytes, inf) < nListBytes) return FALSE;
if (fread(drawlist->t, 1, nTripBytes, inf) < nTripBytes) return FALSE;
/* Allocate and read face and edge lists */
datalist = (PolyDataPtr) malloc(sizeof(PolyDataRec));
if (fread(&datalist->nFaces, 1, sizeof(int), inf) < sizeof(int))
return FALSE;
nFacesBytes = datalist->nFaces * sizeof(FaceRec);
datalist->faces = (FacePtr) malloc(nFacesBytes);
if (fread(&datalist->nEdges, 1, sizeof(int), inf) < sizeof(int))
return FALSE;
nEdgesBytes = datalist->nEdges * sizeof(EdgeRec);
datalist->edges = (EdgePtr) malloc(nEdgesBytes);
if (fread(datalist->faces, 1, nFacesBytes, inf) < nFacesBytes) return FALSE;
if (fread(datalist->edges, 1, nEdgesBytes, inf) < nEdgesBytes) return FALSE;
if (fclose(inf) != 0) return FALSE;
*drawlistp = drawlist;
*datalistp = datalist;
return TRUE;
}
Boolean
WritePDataObj(char *filename, glo_ObjPtr drawlist, PolyDataPtr datalist) {
FILE *outf;
int version, nTrip, nList;
/* Open the file for writing and write type and version number */
if ((outf = fopen(filename, "w")) == NULL) return FALSE;
fwrite("pdataobj", 1, 8, outf);
version = 1;
fwrite(&version, 1, sizeof(int), outf);
/* Write the glo_object list and triplets */
glo_GetLengths(drawlist, &nList, &nTrip);
fwrite(&nList, 1, sizeof(int), outf);
fwrite(&nTrip, 1, sizeof(int), outf);
fwrite(drawlist->list, 1, nList * sizeof(int), outf);
fwrite(drawlist->t, 1, nTrip * 3 * sizeof(float), outf);
/* Write the pdata face and edge info */
fwrite(&datalist->nFaces, 1, sizeof(int), outf);
fwrite(&datalist->nEdges, 1, sizeof(int), outf);
fwrite(datalist->faces, 1, datalist->nFaces * sizeof(FaceRec), outf);
fwrite(datalist->edges, 1, datalist->nEdges * sizeof(EdgeRec), outf);
fclose(outf);
return TRUE;
}
void
AddEdge(EdgePtr edgeList, int *nEdgesp, int v1, int v2, int thisFace,
int *iEdgep, int *iSidep)
{
/* Add an instance of this edge to list. Set face, and vertices if
this is the first occurence of this edge. Don't set next recs.
Return resulting edge index and side in iEdgep, *iSidep. */
int iEdge, iSide, thisEdge;
for (iEdge = 0; iEdge < *nEdgesp; iEdge++) {
/* Check for this edge exists already */
for (iSide=0; iSide<2; iSide++)
if (edgeList[iEdge].e[iSide].face >= 0 &&
edgeList[iEdge].e[iSide].vertex == v1 &&
edgeList[iEdge].e[1-iSide].vertex == v2) {
*iEdgep = iEdge;
*iSidep = iSide;
goto AddNew;
}
/* Check for this edge in the opposite direction */
if (edgeList[iEdge].e[0].face >= 0 &&
edgeList[iEdge].e[0].vertex == v2 &&
edgeList[iEdge].e[1].vertex == v1) {
edgeList[iEdge].e[1].face = thisFace;
*iEdgep = iEdge;
*iSidep = 1;
return;
}
}
/* Need to add a new edge. */
AddNew:
edgeList[*nEdgesp].e[0].face = thisFace;
edgeList[*nEdgesp].e[1].face = -1;
edgeList[*nEdgesp].e[0].vertex = v1;
edgeList[*nEdgesp].e[1].vertex = v2;
*iEdgep = *nEdgesp;
*iSidep = 0;
(*nEdgesp)++;
}
PolyDataPtr
GetPolyData(glo_ObjPtr pdl)
{
/* Compile a list of all edges - their vertices and adjoining faces.
Assume no degenerate edges or polygons.
Rules for edge list data structure:
- edges go in a counterclockwise direction.
- face is the polygon on the left side of the edge.
- this side's vertex is the first vertex, other sides is the second.
- face element value <0 means that side of the edge unused.
- nextEdge/nextSide point at next edge reference in this direction
around the polygon.
*/
int nEdges, nFaces;
FaceRec faceList[MAXFACES];
EdgeRec edgeList[MAXEDGES];
int i, lastv, firstv, *lip, thisFace, thisEdge, thisSide;
int lastEdge, lastSide, firstEdge, firstSide;
PolyDataPtr myPDP;
Boolean done;
enum {nonorm, nperv, nperp} mode;
float edge1[3], edge2[3];
nEdges = 0;
nFaces = 0;
mode = nonorm;
lip = pdl->list;
for (done = FALSE; !done;) {
switch (*lip) {
case NONORM: mode = nonorm; break;
case NPERV: mode = nperv; break;
case NPERP: mode = nperp; break;
case ENDLIST: done = TRUE; break;
case BGNPOLY:
/* Add a poly face record - first, get the normal */
lip++;
thisFace = nFaces++;
switch(mode) {
case nonorm:
/* No normals. Need to compute one */
vsub(pdl->t[lip[1]], pdl->t[lip[0]], edge1);
vsub(pdl->t[lip[2]], pdl->t[lip[1]], edge2);
vcross(edge1, edge2, faceList[thisFace].n);
vnormal(faceList[thisFace].n);
break;
case nperv:
/* Normal per vertex. Still need to get face normal */
/* Skip over normals when calculating edge vectors */
vsub(pdl->t[lip[3]], pdl->t[lip[1]], edge1);
vsub(pdl->t[lip[5]], pdl->t[lip[3]], edge2);
vcross(edge1, edge2, faceList[thisFace].n);
vnormal(faceList[thisFace].n);
break;
case nperp:
/* Normal per polygon; just copy the normal */
vcopy(pdl->t[lip[0]], faceList[thisFace].n);
break;
}
/* then, add each edge of this poly to the master edge list. */
/* Get the first vertex. */
lip += (mode == nonorm) ? 0 : 1;
firstv = *lip;
/* Get the next vertex and add the first edge */
lip += (mode == nperv) ? 2 : 1;
AddEdge(edgeList, &nEdges, firstv, *lip, thisFace,
&firstEdge, &firstSide);
lastv = *lip;
lastEdge = firstEdge;
lastSide = firstSide;
/* While there is another vertex, add an edge to the list */
while (lip[1] >= 0) {
/* Get the next vertex, skipping normals */
lip += (mode == nperv) ? 2 : 1;
/* Add an edge and link the last edge to it */
AddEdge(edgeList, &nEdges, lastv, *lip, thisFace,
&thisEdge, &thisSide);
edgeList[lastEdge].e[lastSide].nextEdge = thisEdge;
edgeList[lastEdge].e[lastSide].nextSide = thisSide;
lastv = *lip;
lastEdge = thisEdge;
lastSide = thisSide;
}
/* Add the final edge to the edge list, link backward & forward */
AddEdge(edgeList, &nEdges, lastv, firstv, thisFace,
&thisEdge, &thisSide);
edgeList[lastEdge].e[lastSide].nextEdge = thisEdge;
edgeList[lastEdge].e[lastSide].nextSide = thisSide;
edgeList[thisEdge].e[thisSide].nextEdge = firstEdge;
edgeList[thisEdge].e[thisSide].nextSide = firstSide;
break;
default: ;
}
/* Consider the next list item */
lip++;
}
/* Allocate and set up a poly data record */
myPDP = (PolyDataPtr) malloc(sizeof(PolyDataRec));
myPDP->nEdges = nEdges;
myPDP->nFaces = nFaces;
myPDP->faces = (FacePtr) malloc(nFaces * sizeof(FaceRec));
for (i = 0; i < nFaces; i++) myPDP->faces[i] = faceList[i];
myPDP->edges = (EdgePtr) malloc(nEdges * sizeof(EdgeRec));
for (i = 0; i < nEdges; i++) myPDP->edges[i] = edgeList[i];
return myPDP;
}